package main

import (
	"context"
	"fmt"
	"log"
	"net/http"

	"github.com/go-redis/redis/v8"
	"github.com/gorilla/websocket"

	"danmaku/utilities"
)

var upgrader = websocket.Upgrader{
	WriteBufferSize:1024,
	ReadBufferSize:1024,
}

var rooms = newRooms()

var ctx = context.Background()

var rdb = NewRedisConn()

var trieTree = utilities.Trie{Word: 0, Child: make(map[rune]*utilities.Trie)}

func main() {
	NewConsumer()
	http.HandleFunc("/", serveHome)
	http.HandleFunc("/illegal", illegalHandle)
	http.HandleFunc("/chat", func(writer http.ResponseWriter, request *http.Request) {
		serveWs(writer, request)
	})
	err := http.ListenAndServe("localhost:9527", nil)
	if err != nil {
		log.Fatal(err)
	}
}

func serveHome(w http.ResponseWriter, r *http.Request) {
	log.Println(r.URL)
	if r.URL.Path != "/" {
		http.Error(w, "Not found", http.StatusNotFound)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}
	http.ServeFile(w, r, "index.html")
}

func illegalHandle(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/illegal" {
		http.Error(w, "Not found", http.StatusNotFound)
		return
	}
	if r.Method != "POST" {
		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
		return
	}
	words := r.PostFormValue("words")
	fmt.Println(words)
	if words == "" {
		http.Error(w, "words值不能为空", http.StatusBadRequest)
		return
	}
	trieTree.Insert(words)
	w.Write([]byte{})
}

func serveWs(writer http.ResponseWriter, request *http.Request) {
	queries := request.URL.Query()
	roomId := queries.Get("room")
	if roomId == "" {
		writer.WriteHeader(400)
		log.Println("room必须")
		return
	}
	_, err := rdb.Get(ctx, fmt.Sprintf("room:%s", roomId)).Result()
	if err == redis.Nil {
		writer.WriteHeader(400)
		log.Println("房间不存在")
		return
	} else if err != nil {
		writer.WriteHeader(500)
		log.Println(err)
		return
	}

	conn, err := upgrader.Upgrade(writer, request, nil)
	if err != nil {
		log.Println(err)
		return
	}

	room, ok := rooms.rooms[roomId]
	if !ok {
		room = &Room{
			id: roomId,
			clients: make(map[*Client]bool),
			leaving: make(chan *Client),
			broadcastMsg: make(chan []byte),
			entering: make(chan *Client),
		}
		go room.broadcast()
		rooms.mux.Lock()
		rooms.rooms[roomId] = room
		rooms.mux.Unlock()
	}
	client := &Client{conn:conn, room:room, bufChan: make(chan []byte, 256)}
	room.entering <-client

	go client.readMsg()
	client.writeMsg()
}
